#pragma once
#include "KeyHashMap.h"
#include "../core.h"
#include "../strings/string_page.h"
#include "SHash.h"
#include <list>
namespace qb{
	namespace base{

		////////////////////////////////////////////////////////////////////////////////
		template<class Type>
		class ObjectPtrPool {
			std::list<Type*>		m_unused;
			int				m_capcity;		// 默认-1,表示全部缓存
			int				m_allocated;
			bool			m_usepool;
		public:
			ObjectPtrPool(int capcity = -1) :m_capcity(capcity), m_allocated(0), m_usepool(true){}
			~ObjectPtrPool(){
				auto it = m_unused.begin();
				for (; it != m_unused.end(); ++it)
				{
					delete *it;
				}
			}
			virtual void OnEntry(Type* entry, int slot)
			{

			}
			void SetUsePool(bool usePool){ m_usepool = usePool; }
			int GetCount()const{ return m_unused.size(); }
			int GetCapcity()const{ return m_capcity; }
			void SetCapcity(int capcity){ m_capcity = capcity; }
			Type* Alloc(){
				if (!m_usepool)
					return new Type();
				Type* type = 0;
				if (!m_unused.empty())
				{
					type = m_unused.front();
					m_unused.pop_front();
				}
				else
					type = new Type();
				m_allocated++;
				return type;
			}
			void Free(Type* t){
				if (!m_usepool)
				{
					delete t;
					return;
				}
				//BASSERT(t);
				m_allocated--;
				if (m_capcity > 0 && (int)m_unused.size() >= m_capcity)
				{
					delete t;
				}
				else
					m_unused.push_back(t);
			}
		};

		class S_CORE_EXPORT StringPtrMap{
			typedef const char* StringId;
			class Util{
			public:
				static bool IsEqual(StringId id1, StringId id2){
					if (id1 != id2 && id1 && id2){
						const char* s1 = id1;
						const char* s2 = id2;
						for (;(*s1)!=0 && (*s2)!=0;++s1,++s2)
						{
							if (*s1 != *s2)
								return false;
						}
						return (*s1) == 0 && (*s2) == 0;
					}
					return id1 == id2;
				}
			};
			struct Key{
				StringId		id;
				const void*		ptr;
			public:
				Key() :id(0), ptr(0){}
				Key(const char* c, const void* p) :id(c), ptr(p){}
				Key(const Key& k) :id(k.id), ptr(k.ptr){}
				inline unsigned int GetHash(){ return qb::base::GetFastHash(id, strlen(id), 0); }
				inline bool operator==(const Key& k){ return id == k.id || Util::IsEqual(id, k.id); }
			};
			struct  Entry{							// 
				Entry*			hashprev;			// 哈西插槽的双链表的后一个
				Entry*			hashnext;			// 哈西插槽的双链表的前一个
				Key				key;				// 用于标志
				Entry() :hashnext(0), hashprev(0){}
			};
			class Collector : public KeyHashMap<Entry, Key>::Listener{
				ObjectPtrPool<Entry>*	m_cache;
			public:
				Collector(ObjectPtrPool<Entry>* pcache) :m_cache(pcache){}
				void Enum(KeyHashMap<Entry, Key>& hashmap){ hashmap.Enum(this); }
				virtual void OnEntry(Entry* entry, int slot){ m_cache->Free(entry); }
			};
			typedef qb::base::StringPage SStringBuf;
			SStringBuf*				m_string_buf;	// 
			KeyHashMap<Entry, Key>	m_hashmap;		// 
			ObjectPtrPool<Entry>	m_cache;		// 
		public:
			StringPtrMap(int capcity);
			~StringPtrMap();
			StringId SetAt(const char* name, void* ptr);
			bool Lookup(const char* name, void*& ptr);
			void RemoveAll();
			void Expand(int capcity){ m_hashmap.Expand(capcity); }
			void ExpandByRatio(double ratio);
			void InitHashTable(int capcity);

			int GetLength()const{ return m_hashmap.GetLength(); }
			double GetHashRatio()const{ return m_hashmap.GetCount()*1.0 / m_hashmap.GetLength(); }
			int  GetBytes()const;
		protected:
			Entry* NewEntry(const Key& k);
		};

	}//namespace base;
}//namespace ss;
